package com.cskaoyan.javase.oop3._0abstract._0introduction._1new;

/**
 * 以下猫狗继承案例，是一个非常基础的继承语法的代码。思考一下Animal类的继承体系，有什么问题吗？
 * 从以下两个角度分析：
 * 从代码角度上，有没有冗余代码？
 *      动物的叫声,Animal类中的shout方法是没有被调用的.
 *      实际上,Animal类中shout方法就是纯粹为了被继承,被重写的,即便它没有方法体也没关系
 *
 * 从设计角度上，在这个案例中，会存在一个动物对象吗？
 *      没有,案例中不存在一个动物对象,它仅仅作为生成子类的一个父类而存在
 *      况且也没有一种动物就叫"动物",Animal更像一个抽象的概念
 *      抽象的概念应该不需要创建对象,抽象的概念的行为也不好描述
 *
 *  以上总结,我们可以改进这个案例,让:
 *      1.Animal类是抽象概念,不需要创建对象,仅作为父类而存在,作用就是生成子类
 *      2.Animal类中的shout方法没必要有方法体
 *  怎么做呢? 需要引用抽象类和抽象方法的概念,使用关键字abstract
 *
 * 1.首先直接去调用shout方法的方法体,报错: Missing method body, or declare abstract
 *      一个方法要么有方法体,要么应该声明为抽象方法
 *      抽象方法的定义语法:
 *      [访问权限修饰符] abstract 返回值类型 方法名(形参列表);
 *
 * 2.直接在普通类中声明抽象方法,会报错:
 *      Class 'Animal' must either be declared abstract or implement abstract method 'shout()' in 'Animal'
 *          一个类如果想要有抽象方法,就必须是抽象类
 *          一个普通类,不允许存在抽象方法
 *      Abstract method in non-abstract class: 抽象方法必须在抽象类中
 *      抽象类的定义语法:
 *      [访问权限修饰符] abstract class 类名{
 *          // 类体
 *      }
 *
 * 3.抽象类定义完毕后,整个代码就不会报错了!
 *
 * 最后,要说明的是: 抽象类仍然是一个类,仍然可以被继承,仍然可以作为一个父类,测试:
 *      1.抽象类无法创建对象
 *      2.抽象类作为父类后,多态仍然存在
 *
 * @since 10:54
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 'Animal' is abstract; cannot be instantiated
        // Animal a = new Animal();
        Animal a;
        a = new Cat();
        a.shout();
        a = new Dog();
        a.shout();
    }
}

abstract class Animal {
    public abstract void shout();
}

class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}

class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}